﻿Public Class InfoBox
    Inherits PictureBox

    Dim Icon As String
    Dim Message As String
    Dim WithEvents Timer As New Timer With {.Interval = 250}
    Dim FlashCount As Integer = 0
    Dim Buttons As New List(Of Button)
    Dim ActiveButton As Button

    Delegate Sub CallerDelegate()

    Sub New()
        ResizeRedraw = True
    End Sub

    Sub Reset()
        ActiveButton = Nothing
        Buttons.Clear()
        Icon = ""
        Message = ""
        Visible = False
    End Sub

    Sub ShowMessage(ByVal Icon As String, ByVal Message As String, Optional ByVal Buttons As String = "")
        Me.Icon = Icon
        Me.Message = Message
        Invalidate()
        Visible = True
        If Buttons = "" Then Exit Sub
        For Each Item In Buttons.Split("|")
            Dim w As Integer = CreateGraphics.MeasureString(Item, Font).Width + 16
            For Each Button In Me.Buttons
                Button.Rect.Offset(-w, 0)
            Next
            Me.Buttons.Add(New Button With {.Text = Item, .Font = Font, .Rect = New Rectangle(0, 0, w, Height - 2)})
        Next
        OnResize(Nothing)
        Flash()
    End Sub

    Sub Bind(ByVal Index As Integer, ByVal Caller As CallerDelegate)
        If Index >= Buttons.Count Then Exit Sub
        Buttons(Index).Caller = Caller
    End Sub

    Sub Flash()
        FlashCount = 0
        Timer.Enabled = True
    End Sub

    Protected Overrides Sub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs)
        Dim R As Rectangle = ClientRectangle
        R.Height -= 1
        pe.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
        pe.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
        R.Width = R.Height
        R.Inflate(-4, -4)
        pe.Graphics.Clear(Color.White)
        If FlashCount Mod 2 = 0 Then
            Select Case Icon
                Case "i" : pe.Graphics.DrawImage(SystemIcons.Information.ToBitmap, R)
                Case "x" : pe.Graphics.DrawImage(SystemIcons.Error.ToBitmap, R)
                Case "!" : pe.Graphics.DrawImage(SystemIcons.Exclamation.ToBitmap, R)
                Case "?" : pe.Graphics.DrawImage(SystemIcons.Question.ToBitmap, R)
            End Select
        End If
        R = ClientRectangle
        R.Width -= R.Height
        R.Height -= 1
        R.Offset(R.Height, 0)
        R.Inflate(-4, -4)
        R.Offset(-4, 0)
        Dim Flags As New TextFormatFlags
        Flags = TextFormatFlags.NoClipping Or TextFormatFlags.VerticalCenter
        TextRenderer.DrawText(pe.Graphics, Message, Parent.Font, R, Color.FromArgb(64, 96, 160), Color.Transparent, Flags)
        pe.Graphics.DrawLine(Pens.Gray, Left, Bottom - 1, Right, Bottom - 1)
        Cursor = If(ActiveButton Is Nothing, Cursors.Default, Cursors.Hand)
        For Each Button In Buttons
            Button.Draw(pe.Graphics, Button Is ActiveButton)
        Next
    End Sub

    Private Sub Timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer.Tick
        FlashCount += 1
        Invalidate()
        If FlashCount = 8 Then Timer.Enabled = False
    End Sub

    Private Sub InfoBox_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
        If ActiveButton Is Nothing Then Exit Sub
        ActiveButton.Caller()
    End Sub

    Private Sub InfoBox_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave
        ActiveButton = Nothing
        Invalidate()
    End Sub

    Class Button
        Public Text As String
        Public Rect As Rectangle
        Public Font As Font
        Public Caller As CallerDelegate

        Sub Draw(ByVal G As Graphics, ByVal Active As Boolean)
            Dim R = Rect
            Dim Alpha As Integer = If(Active, 255, 224)
            R.Inflate(-2, -3)
            G.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
            G.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
            G.PixelOffsetMode = Drawing2D.PixelOffsetMode.None
            G.FillRectangle(New SolidBrush(Color.FromArgb(Alpha, 64, 80, 160)), R)
            R.Inflate(-1, -1)
            G.DrawRectangle(New Pen(Color.FromArgb(Alpha, Color.White)), R)
            Dim F As New StringFormat
            F.LineAlignment = StringAlignment.Center
            F.Alignment = StringAlignment.Center
            G.DrawString(Text, Font, New SolidBrush(Color.FromArgb(Alpha, Color.White)), R, F)
        End Sub
    End Class

    Private Sub InfoBox_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
        ActiveButton = Nothing
        For Each Button In Buttons
            If Button.Rect.Contains(e.Location) Then ActiveButton = Button : Exit For
        Next
        Invalidate()
    End Sub

    Private Sub InfoBox_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        Dim x As Integer = Right - 2
        For i As Integer = Buttons.Count - 1 To 0 Step -1
            Dim Button = Buttons(i)
            x -= Buttons(i).Rect.Width
            Button.Rect.Location = New Point(x, Button.Rect.Top)
        Next
    End Sub

End Class